package com.es.service;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import com.es.bean.User;
import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest;
import org.elasticsearch.action.delete.DeleteRequest;
import org.elasticsearch.action.delete.DeleteResponse;
import org.elasticsearch.action.get.GetRequest;
import org.elasticsearch.action.get.GetResponse;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.index.IndexResponse;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.action.support.master.AcknowledgedResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.sort.SortOrder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.lang.Nullable;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import static com.es.utils.Const.Default_INDEX_NAME;

/**
 * Description:
 *
 * @author weiruibai.vendor
 * Date: 2022/11/21 15:12
 */
@Service
public class ElasticsearchService {

    private static final Logger LOGGER = LoggerFactory.getLogger(ElasticsearchService.class);

    private static final String TYPE = "type";

    @Autowired
    private RestHighLevelClient client;

    /**
     * 添加数据到ES
     * 可能报错：Validation Failed: 1: type is missing;
     * 代替方法：add_v2
     *
     * @param body 添加的数据体
     * @param id
     * @return
     */
    public String add(String body, @Nullable String indexName, String id) {
        if (StringUtils.isEmpty(indexName)) {
            indexName = Default_INDEX_NAME;
        }
        try {
            // 检查默认索引是否已经存在
            IndexRequest request = new IndexRequest(indexName, "_doc");
            //request.index(indexName).id(id);
            request.source(body);
            IndexResponse response = client.index(request, RequestOptions.DEFAULT);
            System.out.println(response.getResult());
        } catch (Exception e) {
            LOGGER.error("err: {}", e);
            return "Fail";
        }
        return "Success";
    }

    public String add(Map body, @Nullable String indexName, String id) {
        if (StringUtils.isEmpty(indexName)) {
            indexName = Default_INDEX_NAME;
        }
        try {
            IndexRequest request = new IndexRequest(indexName, "_doc");
            //request.index(indexName).id(id);
            request.source(body).id(id);
            IndexResponse response = client.index(request, RequestOptions.DEFAULT);
            LOGGER.info("status: {}", response.getResult());
        } catch (Exception e) {
            LOGGER.error("err: {}", e);
            return "Fail";
        }
        return "Success";
    }


    /**
     * 添加数据到ES
     *
     * @param data 添加的数据体
     * @param id
     * @return
     */
    public String add_v2(Object data, @Nullable String indexName, String id) {
        Map<String, String> body = JSON.parseObject(JSON.toJSONString(data),
                new TypeReference<Map<String, String>>() {
                });
        if (StringUtils.isEmpty(indexName)) {
            indexName = Default_INDEX_NAME;
        }
        try {
            // 检查默认索引是否已经存在
            IndexRequest request = new IndexRequest(indexName, TYPE);
            request.source(body).id(id);
            IndexResponse response = client.index(request, RequestOptions.DEFAULT);
            LOGGER.info("status: {}", response.getResult());
        } catch (Exception e) {
            LOGGER.error("err: {}", e);
            return "Fail";
        }
        return "Success";
    }

    /**
     * 从ES查询
     *
     * @param indexName
     * @param id
     * @return
     */
    public String get(@Nullable String indexName, String id) {
        if (StringUtils.isEmpty(indexName)) {
            indexName = Default_INDEX_NAME;
        }
        GetResponse response;
        try {
            GetRequest request = new GetRequest(indexName, "_doc", id);
            response = client.get(request, RequestOptions.DEFAULT);
        } catch (Exception e) {
            LOGGER.error("err: {}", e);
            return "Fail";
        }
        return response.getSourceAsString();
    }

    public String get_v2(@Nullable String indexName, String id) {
        if (StringUtils.isEmpty(indexName)) {
            indexName = Default_INDEX_NAME;
        }
        GetResponse response;
        try {
            GetRequest request = new GetRequest(indexName, TYPE, id);
            //request.index(indexName).id(id);
            response = client.get(request, RequestOptions.DEFAULT);
        } catch (Exception e) {
            LOGGER.error("err: {}", e);
            return "Fail";
        }
        return response.getSourceAsString();
    }

    /**
     * 如果有数据，默认值返回10条记录
     *
     * @param indexName
     * @param user
     * @return
     * @throws IOException
     */
    public List<String> searchByCondition(String indexName, User user) throws IOException {
        if (StringUtils.isEmpty(indexName)) {
            indexName = Default_INDEX_NAME;
        }
        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
        if (null == user || StringUtils.isEmpty(user.getName()) && StringUtils.isEmpty(user.getSex())) {
            // 全文检索
            sourceBuilder.query(QueryBuilders.matchAllQuery());
        } else {
            //创建复合查询条件对象（精确匹配）
            if (!StringUtils.isEmpty(user.getName())) {
                sourceBuilder.query(QueryBuilders.termQuery("name.keyword", user.getName()));
            }
            if (!StringUtils.isEmpty(user.getSex())) {
                sourceBuilder.query(QueryBuilders.termQuery("sex.keyword", user.getSex()));
            }
            if (!StringUtils.isEmpty(user.getAge())) {
                sourceBuilder.query(QueryBuilders.termQuery("age.keyword", user.getAge()));
            }
        }
        /**
         * 分页
         */
        sourceBuilder.from(0);
        sourceBuilder.size(10);
        sourceBuilder.sort("id.keyword", SortOrder.DESC); // 根据id倒序
        LOGGER.info("sourceBuild: {}", sourceBuilder);
        SearchRequest request = new SearchRequest(indexName).source(sourceBuilder).types(TYPE);
        SearchResponse search = client.search(request, RequestOptions.DEFAULT);
        SearchHits hits = search.getHits();
        List res = new ArrayList();
        if (null == hits || hits.getHits().length == 0) {
            return res;
        }
        for (SearchHit hit : hits.getHits()) {
            res.add(hit.getSourceAsString());
        }
        return res;
    }

    public void delete(String IndexName, String id) {
        try {
            DeleteRequest request = new DeleteRequest();
            request.index(Default_INDEX_NAME).id(id);
            DeleteResponse response = client.delete(request, RequestOptions.DEFAULT);
            LOGGER.info("delete Index: {} id: {}, status: {}", Default_INDEX_NAME, id, response.getIndex());
        } catch (Exception e) {
            LOGGER.error("err: {}", e);
        }
    }

    public Boolean deleteIndex(String indexName) throws IOException {
        DeleteIndexRequest deleteIndexRequest = new DeleteIndexRequest(indexName);
        AcknowledgedResponse response = client.indices().
                delete(deleteIndexRequest, RequestOptions.DEFAULT);
        return response.isAcknowledged();
    }

}
